package com.gitee.huanminabc.jcommon.system;

import java.net.NetworkInterface;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Enumeration;

public class MachineCodeGenerator {

    /**
     * 获取本机唯一机器码（long类型）
     *
     * @return long型机器码，唯一且稳定
     * @throws MachineCodeException 获取失败时抛出
     */
    public static long getMachineCode() throws MachineCodeException {
        String macAddresses = getAllMacAddresses();
        byte[] hash = hashString(macAddresses);
        byte[] first8 = Arrays.copyOf(hash, 8);
        BigInteger bi = new BigInteger(1, first8); // 保证正数
        return bi.longValue();
    }

    /**
     * 获取本机唯一机器码（完整BigInteger字符串）
     *
     * @return 机器码的无符号大整数字符串，更适合授权场景
     * @throws MachineCodeException 获取失败时抛出
     */
    public static String getMachineCodeString() throws MachineCodeException {
        String macAddresses = getAllMacAddresses();
        byte[] hash = hashString(macAddresses);
        BigInteger bi = new BigInteger(1, hash); // 取完整256位哈希
        return bi.toString();
    }

    /**
     * 获取所有有效物理网卡的MAC地址拼接字符串
     */
    private static String getAllMacAddresses() throws MachineCodeException {
        try {
            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
            StringBuilder sb = new StringBuilder();
            while (interfaces.hasMoreElements()) {
                NetworkInterface ni = interfaces.nextElement();
                if (ni.isLoopback() || ni.isVirtual() || !ni.isUp()) continue;
                byte[] mac = ni.getHardwareAddress();
                if (mac != null && mac.length > 0) {
                    for (byte b : mac) {
                        sb.append(String.format("%02X", b)); // 不加分隔符，更适合哈希
                    }
                }
            }
            if (sb.length() == 0) {
                throw new MachineCodeException("无法获取任何有效的物理网卡MAC地址");
            }
            return sb.toString();
        } catch (Exception e) {
            throw new MachineCodeException("获取MAC地址失败: " + e.getMessage());
        }
    }

    /**
     * 对字符串进行SHA-256哈希
     */
    private static byte[] hashString(String input) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            return digest.digest(input.getBytes(StandardCharsets.UTF_8));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 机器码相关异常
     */
    public static class MachineCodeException extends Exception {
        public MachineCodeException(String msg) { super(msg); }
    }

    public static void main(String[] args) {
        try {
            long machineCode = getMachineCode();
            String machineCodeStr = getMachineCodeString();
            System.out.println("机器码（long）: " + machineCode);
            System.out.println("机器码（有符号16进制）: " + Long.toHexString(machineCode));
            System.out.println("机器码（无符号16进制）: " + Long.toUnsignedString(machineCode, 16));
            System.out.println("机器码（BigInteger字符串）: " + machineCodeStr);
        } catch (MachineCodeException e) {
            e.printStackTrace();
        }
    }
}